// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information

package testplanet

import (
	"context"
	"runtime/pprof"
	"testing"

	"storj.io/common/testcontext"
	"storj.io/private/dbutil/pgtest"
	"storj.io/storj/private/testmonkit"
	"storj.io/storj/satellite/satellitedb/satellitedbtest"
	"storj.io/uplink"
)

// Run runs testplanet in multiple configurations.
func Run(t *testing.T, config Config, test func(t *testing.T, ctx *testcontext.Context, planet *Planet)) {
	databases := satellitedbtest.Databases()
	if len(databases) == 0 {
		t.Fatal("Databases flag missing, set at least one:\n" +
			"-postgres-test-db=" + pgtest.DefaultPostgres + "\n" +
			"-cockroach-test-db=" + pgtest.DefaultCockroach)
	}

	for _, satelliteDB := range databases {
		satelliteDB := satelliteDB
		t.Run(satelliteDB.Name, func(t *testing.T) {
			parallel := !config.NonParallel
			if parallel {
				t.Parallel()
			}

			if satelliteDB.MasterDB.URL == "" {
				t.Skipf("Database %s connection string not provided. %s", satelliteDB.MasterDB.Name, satelliteDB.MasterDB.Message)
			}
			planetConfig := config
			if planetConfig.Name == "" {
				planetConfig.Name = t.Name()
			}

			log := newLogger(t)

			testmonkit.Run(context.Background(), t, func(parent context.Context) {
				ctx := testcontext.NewWithContext(parent, t)
				defer ctx.Cleanup()

				pprof.Do(ctx, pprof.Labels("planet", planetConfig.Name), func(namedctx context.Context) {
					planet, err := NewCustom(namedctx, log, planetConfig, satelliteDB)
					if err != nil {
						t.Fatalf("%+v", err)
					}
					defer ctx.Check(planet.Shutdown)

					planet.Start(namedctx)

					provisionUplinks(namedctx, t, planet)

					test(t, ctx, planet)
				})
			})
		})
	}
}

func provisionUplinks(ctx context.Context, t *testing.T, planet *Planet) {
	for _, planetUplink := range planet.Uplinks {
		for _, satellite := range planet.Satellites {
			apiKey := planetUplink.APIKey[satellite.ID()]
			access, err := uplink.RequestAccessWithPassphrase(ctx, satellite.URL(), apiKey.Serialize(), "")
			if err != nil {
				t.Fatalf("%+v", err)
			}
			planetUplink.Access[satellite.ID()] = access
		}
	}
}
